﻿using Net.Event;
using System;
using System.Threading;

namespace Net.System
{
    public class ThreadWorker
    {
        private Thread thread;
        private readonly QueueSafe<ValueTuple<WaitCallback, object>> taskQueue = new();
        private readonly AutoResetEvent taskAvailable = new(false);
        private readonly ManualResetEvent stopEvent = new(false);

        public Action<Exception> OnException { get; set; }
        public bool Idle { get; internal set; }

        public void Start(string name)
        {
            thread = new Thread(DoWorker)
            {
                Name = name,
                IsBackground = true
            };
            thread.Start();
        }

        private void DoWorker()
        {
            while (!stopEvent.WaitOne(0))
            {
                Idle = true;
                taskAvailable.WaitOne();
                Idle = false;
                while (taskQueue.TryDequeue(out var result))
                {
                    try
                    {
                        result.Item1(result.Item2);
                    }
                    catch (Exception ex)
                    {
                        if (OnException == null)
                            NDebug.LogError("线程池异常:" + ex);
                        else
                            OnException(ex);
                    }
                }
            }
        }

        public void QueueTask(WaitCallback callback, object state)
        {
            taskQueue.Enqueue((callback, state));
            taskAvailable.Set();
        }

        public void Stop()
        {
            stopEvent.Set();
            taskAvailable.Set();
            thread.Join();
        }

        public override string ToString()
        {
            return $"Name:{thread.Name} IsIdle:{Idle} Queue:{taskQueue.Count}";
        }
    }
}